
/**
 * Copyright 2009 cestum.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package org.waveprotocol.wave.model.document.operation.algorithm.transformer
{
import org.goverla.collections.ArrayList;
import org.waveprotocol.wave.model.document.operation.AnnotationBoundaryMap;
import org.waveprotocol.wave.model.document.operation.algorithm.ValueUpdate;
import org.waveprotocol.wave.model.document.operation.impl.AnnotationBoundaryMapImpl;

public final class ServerAnnotationTracker extends AnnotationTracker {
	
	var serverAnnotationProcessor:AnnotationProcessor;
	var clientAnnotationProcessor:AnnotationProcessor;
	var clientAnnotationTracker:AnnotationTracker;
	
	public function ServerAnnotationTracker(
		processor:AnnotationProcessor, 
		clientProcessor: AnnotationProcessor,
		clientTracker: AnnotationTracker) {
		super(processor);
		this.clientAnnotationProcessor = clientProcessor;
		this.serverAnnotationProcessor = processor;
		this.clientAnnotationTracker = clientTracker;
	}
	
	override    function processUpdate(map:AnnotationBoundaryMap):void {
		// TODO: This seems pretty awkward. Perhaps we should give
		// AnnotationBoundaryMapImpl an easier builder to use.
		var serverEndKeys:ArrayList= new ArrayList();
		var serverChangeKeys:ArrayList= new ArrayList();
		var serverChangeOldValues:ArrayList= new ArrayList();
		var serverChangeNewValues:ArrayList= new ArrayList();
		var clientEndKeys:ArrayList= new ArrayList();
		var clientChangeKeys:ArrayList= new ArrayList();
		var clientChangeOldValues:ArrayList= new ArrayList();
		var clientChangeNewValues:ArrayList= new ArrayList();
		for (var i:int= 0; i < map.endSize(); ++i) {
			var key:String= map.getEndKey(i);
			var clientValues:ValueUpdate= ValueUpdate(clientAnnotationTracker.active.getItem(key));
			if (clientValues != null) {
				clientChangeKeys.addItem(key);
				clientChangeOldValues.addItem(clientValues.oldValue);
				clientChangeNewValues.addItem(clientValues.newValue);
			} else {
				serverEndKeys.addItem(key);
			}
		}
		for (var i:int= 0; i < map.changeSize(); ++i) {
			var key:String= map.getChangeKey(i);
			var oldValue:String= map.getOldValue(i);
			var newValue:String= map.getNewValue(i);
			var clientValues:ValueUpdate= ValueUpdate(clientAnnotationTracker.active.getItem(key));
			if (clientValues != null) {
				clientChangeKeys.addItem(key);
				clientChangeOldValues.addItem(newValue);
				clientChangeNewValues.addItem(clientValues.newValue);
			} else {
				serverChangeKeys.addItem(key);
				serverChangeOldValues.addItem(oldValue);
				serverChangeNewValues.addItem(newValue);
			}
		}
		serverAnnotationProcessor.process(new AnnotationBoundaryMapImpl(
			serverEndKeys.toArray(),
			serverChangeKeys.toArray(),
			serverChangeOldValues.toArray(),
			serverChangeNewValues.toArray()));
		clientAnnotationProcessor.process(new AnnotationBoundaryMapImpl(
			clientEndKeys.toArray(),
			clientChangeKeys.toArray(),
			clientChangeOldValues.toArray(),
			clientChangeNewValues.toArray()));
	}
	
	
	override  function opposingTracker():AnnotationTracker {
		return clientAnnotationTracker;
	}
	
}
}